package cn.git.agent;

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.utility.JavaModule;

/**
 * @description: 监听器
 * @program: bank-credit-sy
 * @author: lixuchun
 * @create: 2024-12-19
 */
public class ByteBuddyListener implements AgentBuilder.Listener {

    /**
     * 当一个类型被发现时调用，就会回调此方法
     *
     * @param typeName    The binary name of the instrumented type.
     * @param classLoader The class loader which is loading this type or {@code null} if loaded by the boots loader.
     * @param module      The instrumented type's module or {@code null} if the current VM does not support modules.
     * @param loaded      {@code true} if the type is already loaded.
     */
    @Override
    public void onDiscovery(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) {
        if (typeName.contains("TestController")) {
            System.out.println("onDiscovery: " + typeName);
        }
    }

    /**
     * 对某一个类型进行转换时调用，就会回调此方法
     *
     * @param typeDescription The type that is being transformed.
     * @param classLoader     The class loader which is loading this type or {@code null} if loaded by the boots loader.
     * @param module          The transformed type's module or {@code null} if the current VM does not support modules.
     * @param loaded          {@code true} if the type is already loaded.
     * @param dynamicType     The dynamic type that was created.
     */
    @Override
    public void onTransformation(TypeDescription typeDescription,
                                 ClassLoader classLoader,
                                 JavaModule module,
                                 boolean loaded,
                                 DynamicType dynamicType) {
        System.out.println("onTransformation: " + typeDescription.getActualName());
    }

    /**
     * 当某一个类被加载并且被忽略时(包括ignore配置或不匹配)调用，就会回调此方法
     *
     * @param typeDescription The type being ignored for transformation.
     * @param classLoader     The class loader which is loading this type or {@code null} if loaded by the boots loader.
     * @param module          The ignored type's module or {@code null} if the current VM does not support modules.
     * @param loaded          {@code true} if the type is already loaded.
     */
    @Override
    public void onIgnored(TypeDescription typeDescription,
                          ClassLoader classLoader,
                          JavaModule module,
                          boolean loaded) {
//        log.info("onIgnored: {}", typeDescription.getActualName());
//        System.out.println("onIgnored: " + typeDescription.getActualName());
    }

    /**
     * 当transform过程中发生异常时，会回调此方法
     *
     * @param typeName    The binary name of the instrumented type.
     * @param classLoader The class loader which is loading this type or {@code null} if loaded by the boots loader.
     * @param module      The instrumented type's module or {@code null} if the current VM does not support modules.
     * @param loaded      {@code true} if the type is already loaded.
     * @param throwable   The occurred error.
     */
    @Override
    public void onError(String typeName,
                        ClassLoader classLoader,
                        JavaModule module,
                        boolean loaded,
                        Throwable throwable) {
        System.out.println("onError: " + typeName);
        throwable.printStackTrace();
    }

    /**
     * 当某一个类被处理完，不管是transform还是忽略时，都会回调此方法
     *
     * @param typeName    The binary name of the instrumented type.
     * @param classLoader The class loader which is loading this type or {@code null} if loaded by the boots loader.
     * @param module      The instrumented type's module or {@code null} if the current VM does not support modules.
     * @param loaded      {@code true} if the type is already loaded.
     */
    @Override
    public void onComplete(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) {
//        log.info("onComplete: {}", typeName);
//        System.out.println("onComplete: " + typeName);
    }
}
